﻿#include "cybertron/node/WorkAppWithHotArea.hpp"
#include "NodeInternalServer.hpp"

CYBERTRON_BEGIN

CybertronCoreAPI WorkAppWithHotArea::WorkAppWithHotArea()
{
	zeroMembers();
}

CybertronCoreAPI WorkAppWithHotArea::~WorkAppWithHotArea()
{
	clearThis();
}

void WorkAppWithHotArea::zeroMembers()
{
	mPreviousCalculateFpsTime = std::chrono::high_resolution_clock::now();
	mNumFramesSincePreviousTime = 0;
	mFpsMul10 = -1;
	mNodeTimerIP = "127.0.1.1";
	mNodeTimerPort = 11111;
}

void WorkAppWithHotArea::clearThis()
{
	mHotAreaManager.clear();

	zeroMembers();
}

CybertronCoreAPI int WorkAppWithHotArea::beforeRun() {

	int ret =WorkApp::beforeRun();
	if (ret != 0)
	{
		logError("WorkAppWithHotArea beforeRun %d", ret);
		return ret;
	}
#if defined(NDEBUG)
	for (int i = 0; i < 240; i++)
#else
	while (true)
#endif // DEBUG
	 {
		std::this_thread::sleep_for(std::chrono::seconds(1));
		logInfo("================Wait Node State Ready");
		Common::EWorkNodeState s = mWorkState.load(memory_order_relaxed);
		if(!mbAgentThreadRunning){
			return 0;
		}
		if (s == Common::EWorkNodeStateEndingWork) {
			logError("================Wait Node State Ending Work= %d", s);
			return -1;
		}
		else if (s >= Common::EWorkNodeStateInitFinish) {
			logInfo("================Wait Node State Ready Is OK");
			return 0;
		}
	}
	Common::EWorkNodeState s = mWorkState.load(memory_order_relaxed);
	logError("================Wait Node State Time Out= %d", s);
	return ret;

}
CybertronCoreAPI bool WorkAppWithHotArea::onTaskStartBefore(){
	WorkApp::onTaskStartBefore();
	WorkNodeNetInfo* pWorkNodeNetInfo = getWorkNodeNetInfo(Common::EWorkNodeType_CybertronNodeTimer);
	if (pWorkNodeNetInfo == nullptr){
		logError("WorkAppWithHotArea can not get WorkNodeNetInfo");
		return false;
	}
	logInfo("======pWorkNodeNetInfo change server node ip ==>%s ,local ip==>%s",pWorkNodeNetInfo->publicIP.c_str(), mAgentPublicIP.c_str());
	//if (mAgentPublicIP == pWorkNodeNetInfo->publicIP) {
	//	mNodeTimerIP = "127.0.0.1";
	//}
	//else {
	//	mNodeTimerIP = pWorkNodeNetInfo->publicIP;
	//}
	mNodeTimerIP = pWorkNodeNetInfo->publicIP;
	mNodeTimerPort = pWorkNodeNetInfo->publicPort;
	return true;
}

CybertronCoreAPI bool WorkAppWithHotArea::init(int argc, char* argv[])
{
	WorkApp::init(argc, argv);

	if (!mHotAreaManager.initialize(this))
	{
		logError("Can not initialize hotarea manager.");
		return false;
	}
	setServerListenPort(mHotAreaManager.getFoundationServerPort());

	mPreviousCalculateFpsTime = std::chrono::high_resolution_clock::now();

	return true;
}

CybertronCoreAPI void WorkAppWithHotArea::clear()
{
	clearThis();
}

CybertronCoreAPI void WorkAppWithHotArea::handleTimer()
{
	//1秒跑多少次?
	if (mWorkState <= Common::EWorkNodeStateInitFinish) {
		return;
	}
	mNumFramesSincePreviousTime++;

	auto t = std::chrono::high_resolution_clock::now();
	std::chrono::nanoseconds span = t - mPreviousCalculateFpsTime;
	std::uint64_t tick = span.count();
	//如果相隔1秒
	if (tick / 1000000 > 1000)
	{
		//每10秒多少帧
		mFpsMul10 = (int)((std::uint64_t)mNumFramesSincePreviousTime * 10000000000 / tick);
		mNumFramesSincePreviousTime = 0;
		mPreviousCalculateFpsTime = t;
	}

	mHotAreaManager.onTimer();
}

CybertronCoreAPI bool WorkAppWithHotArea::getDisconnected() const
{
	return mHotAreaManager.getDisconnected();
}

CybertronCoreAPI bool WorkAppWithHotArea::connectNodeTimer()
{
	return mHotAreaManager.connectNodeTimer(mNodeTimerIP, mNodeTimerPort);
}



CybertronCoreAPI int WorkAppWithHotArea::getFpsMul10() const
{
	return mFpsMul10;
}

std::uint32_t WorkAppWithHotArea::getNumThreads() const
{
	return 1;
}

bool WorkAppWithHotArea::onLoadConfig() {
	return WorkApp::onLoadConfig();
}

CybertronCoreAPI bool WorkAppWithHotArea::onConnectNodeTimerAfter()
{
	Common::EWorkNodeType workType = mSeflWorkNodeBaseConfig.workType;
	if (!mHotAreaManager.networkDeclareRole(mSeflWorkNodeBaseConfig.hz, mSeflWorkNodeBaseConfig.workName))
	{
		return false;
	}

	if (workType == Common::EWorkNodeType_CybertronVisualizer
		|| workType == Common::EWorkNodeType_CybertronObserver
		|| workType == Common::EWorkNodeType_CybertronVR)
	{
		
		mHotAreaManager.setProcessTimeStepForwardMessageOneByOne(false);
	}
	else {
		if (mSeflWorkNodeBaseConfig.joinTimeSync) {
			if (!mHotAreaManager.networkJoinTimeLoop())
			{
				return false;
			}
			mHotAreaManager.setProcessTimeStepForwardMessageOneByOne(true);
		}
		else{
			mHotAreaManager.setProcessTimeStepForwardMessageOneByOne(false);
		}
	}
	//mHostVehiclesBaseConfigMap
	/*if (workType == Common::EWorkNodeType_CybertronVehicleDynamic
		|| workType == Common::EWorkNodeType_CybertronVR)*/ 
	if(isNeedCreateHotArea()){

		string hostVehiclesId = mSeflWorkNodeBaseConfig.dependHotAreaList[0];
		int actorIdInt = atoi(hostVehiclesId.c_str());
		int assetId = 0;
		HostVehiclesBaseConfigMap::iterator it = mHostVehiclesBaseConfigMap.find(hostVehiclesId);
		if (it == mHostVehiclesBaseConfigMap.end()) {
			return false;
		}

		auto hotAreaRadius = it->second.hotAreaRange;
		cybertron::vec3 pos;
		cybertron::vec3 rot;
		cybertron::vec3 size;

		pos.x = it->second.posX;
		pos.y = it->second.posY;
		pos.z = it->second.posZ;
		rot.x = it->second.rotX;
		rot.y = it->second.rotY;
		rot.z = it->second.rotZ;
		size.x = 5;
		size.y = 2;
		size.z = 1.8f;
		if (!mHotAreaManager.networkCreateHotArea(actorIdInt, pos, rot, hotAreaRadius))
		{
			return false;
		}
		mHotAreaManager.createActor(
			actorIdInt,
			HotArea::EActorType_MainVehicle,
			assetId,
			size,
			pos,
			rot);
	}
	else {
			
		for (size_t i = 0; i < mSeflWorkNodeBaseConfig.dependHotAreaList.size(); i++)
		{
			string hostVehiclesId = mSeflWorkNodeBaseConfig.dependHotAreaList[i];
			int actorIdInt = atoi(hostVehiclesId.c_str());
			int tryCount = 0;
			while (true) {
				bool succ = mHotAreaManager.networkSubscribeHotArea(actorIdInt);
				if (succ) {
					logInfo("subscribe hot area success");
					break;
				}
				logWarning("retry hot area subscription");
				std::this_thread::sleep_for(std::chrono::seconds(1));
				tryCount += 1;
				if (tryCount >= 30) {
					logError("subscribe hot area fail");
					return false;
				}
			}
		}
		return true;
	}

	return true;
}

CybertronCoreAPI void WorkAppWithHotArea::onTimer(
	int framestamp,
	int ms)
{
}

CybertronCoreAPI void WorkAppWithHotArea::onTimer(
	int framestamp,
	int ms,
	int msModNs)
{
}

CybertronCoreAPI void WorkAppWithHotArea::onPlay()
{
}

CybertronCoreAPI void WorkAppWithHotArea::onPause()
{
}

CybertronCoreAPI void WorkAppWithHotArea::onReset()
{
}
CybertronCoreAPI  void WorkAppWithHotArea::onCaseStart() {

}
CybertronCoreAPI  void WorkAppWithHotArea::onCaseStop() {

}
// CybertronCoreAPI void WorkAppWithHotArea::broadcast(const Message& msg)
// {
// 	mHotAreaManager.mpNodeFoundationServer->broadcast(msg);
// }

CybertronCoreAPI WorkAppWithHotArea::EHandleResult WorkAppWithHotArea::onMessageDirect(
	SocketBasePtr pSender,
	const Message& msg)
{
	return EHandleResult_Unhandled;
}

CybertronCoreAPI void WorkAppWithHotArea::onMessageCommand(std::uint32_t msgId, const std::string * msgDataBody)
{
}
CybertronCoreAPI void WorkAppWithHotArea::onChannelSubData(std::string Channel, std::uint32_t msgId, const std::string* msgDataBody) {
}
CybertronCoreAPI void WorkAppWithHotArea::onClientConnection(
	SocketBasePtr pClientSocket,
	ESocketStatus status)
{
}

CybertronCoreAPI std::string WorkAppWithHotArea::onControlCommand(
	const std::string controlCommand)
{
	return std::string();
}
bool WorkAppWithHotArea::onTaskStop() {
	onEnd();
	onEnd(mTaskStopFromeAgent.reason());
	return true;
}
CybertronCoreAPI void WorkAppWithHotArea::onEnd()
{
}

CybertronCoreAPI void WorkAppWithHotArea::onEnd(Common::ETaskEndReason reason)
{
}



CYBERTRON_END
